package com.qrxl.util;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qrxl.common.exception.CustomException;
import com.qrxl.common.vo.BaseQuery;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 字符串常用工具
 *
 * @author
 */
public class StringUtil {
    static Logger logger = LoggerFactory.getLogger(StringUtil.class);
    private final static String STAR = "*********************************";

    /**
     * 把null 转为“”
     *
     * @param str
     * @return
     */
    public static String getNotNullStr(String str) {
        if (StringUtils.isEmpty(str)) {
            return "";
        }
        return str;
    }

    /**
     * 把所有回车换行替换掉
     *
     * @param str
     * @return
     */
    public static String replaceAllEnter(String str) {
        if (StringUtils.isEmpty(str)) {
            return "";
        }
        return str.replaceAll("\r|\n", "");
    }

    /**
     * 判断当前用户是否是脱敏用户
     *
     * @param flag
     * @return boolean
     * @author yuanchang
     * @date:2016年8月16日
     */
    public static boolean isSensitiveUser(Integer flag) {
        return flag != null && flag == 1;
    }

    /**
     * 隐藏身份证号中间几位数
     *
     * @param certification 身份证号
     */
    public static String getCertificationById(String certification) {
        if (StringUtils.isEmpty(certification)) {
            return "";
        } else {
            int length = certification.length();
            int v = (int) Math.ceil(length * 0.05);
            return certification.substring(0, v) + STAR.substring(0, length - 2 * v) + certification.substring(length - v);
        }
    }

    /**
     * 手机号脱敏
     *
     * @param phoneNum 手机号
     * @return java.lang.String
     * @author xiabixiang@lansent.com
     * @date 2019/4/11 14:34
     **/
    public static String getPhoneNum(String phoneNum) {
        if (StringUtils.isEmpty(phoneNum)) {
            return null;
        }
        return phoneNum.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
    }


    /**
     * uuid 使用不带-符号的结果
     *
     * @return
     */
    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 返回随机数，指定长度
     *
     * @param length
     * @return
     */
    public static String getRandomString(int length) {
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(62);
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }


    /**
     * 返回数字随机数，指定长度
     *
     * @param length
     * @return
     */
    public static String getRandomNum(int length) {
        // X位随机验证码生成
        StringBuilder stringBuilder = new StringBuilder(length);
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            stringBuilder.append((random.nextInt(9)));
        }
        return stringBuilder.toString();
    }

    public static int getInteger(String str) {
        if (null == str) {
            return 0;
        } else {
            return Integer.parseInt(str);
        }
    }

    public static BigDecimal getBigDecimal(String val) {
        try {
            BigDecimal big = new BigDecimal(val);
            return big.setScale(2, BigDecimal.ROUND_HALF_UP);
        } catch (Exception e) {
            return null;
        }
    }

    public static boolean isMobile(String str) {
        return StringUtils.isEmpty(str) ? false : str.matches("^1[0-9]{10}$");
    }

    public static String md5(String val) {
        char[] hexDegits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            md.update(val.getBytes("UTF-8"));
            byte[] tmp = md.digest();
            char[] tmpStr = new char[32];
            int k = 0;
            for (int i = 0; i < 16; i++) {
                byte b = tmp[i];
                tmpStr[k++] = hexDegits[b >>> 4 & 0xf];
                tmpStr[k++] = hexDegits[b & 0xf];
            }

            return new String(tmpStr);
        } catch (Exception ex) {
            return null;
        }
    }

    public static String cleanXSS(String value) {
        value = value.replaceAll("<", "&LT;").replaceAll(">", "&GT;");
        value = value.replaceAll("\\(", "&#40;").replaceAll("\\)", "&#41;");
        value = value.replaceAll("'", "&#39;");
        value = value.replaceAll("eval\\((.*)\\)", "");
        value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
        return value;
    }

    /**
     * 获取当前系统时间字符串，格式化形式：“yyyy-MM-dd_HH:mm:ss”
     *
     * @return 当前时间字符串
     */
    public static String getCurrentTimeStr() {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
        // 获取当前时间
        Date curDate = new Date(System.currentTimeMillis());
        return formatter.format(curDate);
    }


    /**
     * 隐藏手机号中间四位数
     *
     * @param mobile 11位手机号码
     * @return 中间四位使用”****“表示的手机号
     */
    public static String getNikenameByMobile(String mobile) {
        if (StringUtils.isEmpty(mobile)) {
            return "";
        } else {
            mobile = mobile.replace(" ", "");
            if (mobile.length() == 11) {
                return mobile.substring(0, 3) + "****" + mobile.substring(7, mobile.length());
            } else {
                return mobile.substring(0, 3) + "*******";
            }
        }
    }


    /**
     * desc:通过身份证获取性别(code)
     *
     * @author zhoukun on
     */
    public static String getGendercode(String identification) {
        try {
            int gender = Integer.parseInt(identification.substring(identification.length() - 2, identification.length() - 1));
            // 性别
            if (gender % 2 == 1) {
                return "1";
            } else {
                return "2";
            }
        } catch (Exception e) {
            return "0";
        }
    }


    /**
     * desc:Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map
     *
     * @author zhoukun on
     */
    public static Map<String, Object> transBean2Map(Object obj) {
        if (obj == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();

                // 过滤class属性
                if (!"class".equals(key)) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);
                    map.put(key, value);
                }

            }
        } catch (Exception e) {
            System.out.println("transBean2Map Error " + e);
        }
        return map;
    }


    /**
     * 判断用户登录是否pc客户端
     *
     * @param userAgent
     * @return true:PC客户端，false：非PC客户端
     */
    public static boolean isFxClient(String userAgent) {
        return userAgent.contains("FxClient/1.0");
    }

    /**
     * 判断前一个字符串拆分的数组是否包含第二个字符串
     */
    public static boolean isArrayContains(String str1, String split, String str2) {
        if (StringUtils.isEmpty(str1)) {
            return false;
        }
        String[] array = str1.split(split);
        for (String str : array) {
            if (str.equals(str2)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 对密码进行强校验
     * 1、密码长度取值范围为6~32个字符，最短建议为6个字符；
     * 2、密码中至少需要包括一个大写字母（A~Z）、一个小写字母（a~z）、一个数字字符（0~9），支持特殊字符；
     */
    public static void validatePassword(String password) {
        JGAssert.isRange(password, 6, 32, "密码长度不能小于6或大于32");
        if (!password.matches("^.*[a-z]+.*$")) {
            throw new CustomException("至少要包含一个小写字母（a~z）");
        }
        if (!password.matches("^.*[A-Z]+.*$")) {
            throw new CustomException("至少要包含一个大写字母（A~Z）");
        }
        if (!password.matches("^.*[0-9]+.*$")) {
            throw new CustomException("至少要包含一个数字字符（0~9）");
        }
        if (password.matches("^.*[\\s]+.*$")) {
            throw new CustomException("不能包含空白字符");
        }
    }

    /**
     * 对密码进行强校验
     * 0、必须是半角字符
     * 1、密码长度取值范围为6~32个字符，最短建议为6个字符；
     * 2、密码中至少需要包括一个大写字母（A~Z）、一个小写字母（a~z）、一个数字字符（0~9），支持特殊字符；
     */
    public static void validateUpdatePassword(String password) {
        JGAssert.isRange(password, 6, 32, "密码长度不能小于6或大于32");
        if (!isAllSubOfASCII(password)) {
            throw new CustomException("必须包含6~32位大小写英文和数字(支持特殊字符)");
        }
        validatePassword(password);
    }

    public static QueryWrapper buildBaseQuery(Object target, BaseQuery baseQuery, Object source) {
        if (target == null) {
            throw new CustomException("查询对象不能为空");
        }
        if (source != null) {
            BeanUtils.copyProperties(source, target);
        }
        setBankNull(target);
        QueryWrapper wrapper = Wrappers.query(target);
        if (baseQuery.getId() != null) {
            wrapper.eq("id", baseQuery.getId());
        }
        if (StringUtils.isNoneBlank(baseQuery.getOperator())) {
            wrapper.eq("operator", baseQuery.getOperator());
        }
        if (baseQuery.getStartCreateTime() != null) {
            wrapper.gt("create_time", baseQuery.getStartCreateTime());
        }
        if (baseQuery.getEndCreateTime() != null) {
            wrapper.lt("create_time", baseQuery.getEndCreateTime());
        }
        if (baseQuery.getStartUpdateTime() != null) {
            wrapper.gt("update_time", baseQuery.getStartUpdateTime());
        }
        if (baseQuery.getEndUpdateTime() != null) {
            wrapper.lt("update_time", baseQuery.getEndUpdateTime());
        }
        wrapper.orderByDesc("update_time");
        return wrapper;
    }

    //        将空字符串设置为null
    public static void setBankNull(Object obj) {
        Class<? extends Object> reqClass = obj.getClass();
        for (Field field : reqClass.getDeclaredFields()) {
            String name = field.getName();  //获得对象的属性名称
            if (name.equalsIgnoreCase("serialVersionUID")) {
                continue;
            }
            name = name.substring(0, 1).toUpperCase() + name.substring(1);  //构造get方法的名字
            try {
                Method gm = reqClass.getMethod("get" + name);
                Object value = gm.invoke(obj);
                if (value != null && StringUtils.isEmpty(value.toString())) {
                    field.setAccessible(true);
                    field.set(obj, null);
                }
            } catch (Exception e) {
                logger.error("反射方法调用错误", e);
            }
        }
    }


    //驼峰转下划线
    public static String camelToUnderline(String param, Integer charType) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (Character.isUpperCase(c)) {
                sb.append("_");
            }
            if (charType == 2) {
                sb.append(Character.toUpperCase(c));  //统一都转大写
            } else {
                sb.append(Character.toLowerCase(c));  //统一都转小写
            }


        }
        return sb.toString();
    }

    /**
     * 判断是否全部是半角字符
     *
     * @param str
     * @return
     */
    public static boolean isAllSubOfASCII(String str) {
        return !str.matches("^.*[^\\x00-\\xff]+.*$");
    }

    public static void main(String[] args) throws Exception {
//        System.out.println(StringUtil.replaceAllEnter("xxsdfasdf\n1111"));
//        System.out.println(StringUtil.replaceAllEnter("xxsdfasdf\n\r2222"));
//        System.out.println(StringUtil.replaceAllEnter("xxsdfasdf\r\n3333"));

        validatePassword("12abAB!@#$%^&*()_+|?:><");
        System.out.println("ok");

//        String jti = StringUtil.getRandomString(16);
//        UserAuthReq userAuthReq = new UserAuthReq(jti, null, "127.0.0.1", EnumLoginSource.AC.getCode(), "aaaaa");
//        Date date = DateTime.now().plusSeconds(1).toDate();
//        userAuthReq.setExp(date);
//        String token = JwtUtils.generateToken(userAuthReq);

//        System.out.println("jti:" + jti);
//        System.out.println(token);
    }
}
